﻿using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.IO;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json.Linq;
using RestfulApiV1.Data.Entity;
using RestfulApiV1.Domain.Configure;
using RestfulApiV1.Domain.DTOs;
using RestfulApiV1.Domain.DTOs.Token;
using RestfulApiV1.Implement.Paged;
using RestfulApiV1.Interface.Data;
using RestfulApiV1.Utils.Auth;
using RestfulApiV1.Utils.Json;

// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace RestfulApiV1.Api.Controllers
{
    [Route("api/[controller]")]
    //[Authorize]
    [ApiController]
    public class UsersController : ControllerBase
    {
        private readonly IRespository<Users> _usersRespository;
        private readonly IRespository<UserRole> _userRoleRespository;
        private readonly IWebHostEnvironment _env;
        private TokenParameter _tokenParameter = new TokenParameter();
        private readonly IConfiguration _configuration;

        public UsersController(IRespository<Users> usersRespository, IRespository<UserRole> userRoleRespository, 
            IWebHostEnvironment env, IConfiguration configuration)
        {
            _usersRespository = usersRespository;
            _userRoleRespository = userRoleRespository;
            _env = env;
            _configuration = configuration;

            var config = new ConfigurationBuilder()
                .SetBasePath(AppContext.BaseDirectory)
                .AddJsonFile("appsettings.json")
                .Build();

            _tokenParameter = config.GetSection("TokenParameter").Get<TokenParameter>();
        }

        /// <summary>
        /// 获取所有用户
        /// </summary>
        /// <returns></returns>
        // GET: api/<UsersController>
        [HttpGet]
        public string Get(int pageIndex=1,int pageSize=10)
        {
            var list = _usersRespository.Table
                .Where(x=>x.IsDeleted==false);

            //var resData = new
            //{
            //    PageIndex=pageIndex,
            //    PageSize=pageSize,
            //    TotalItem=totalItem,
            //    TotalPage=totalPage,
            //    Data= new Pagination<Users>(list,pageIndex,pageSize)
            //};

            var res = new
            {
                Code = 1000,
                Data =GetDynamic(new Pagination<Users>(list, pageIndex, pageSize)),
                Msg = "获取 用户列表成功"
            };

            return JsonHelper.SerializeObject(res);
        }

        // GET api/<UsersController>/5
        [HttpGet("{id}")]
        public string Get(int id)
        {
            var user = _usersRespository.GetById(id);

            var res = new
            {
                Code = 1000,
                Data = GetDynamic(user),
                Msg = "获取指定用户成功"
            };

            return JsonHelper.SerializeObject(res);
        }

        /// <summary>
        /// 增加用户
        /// </summary>
        /// <param name="item"></param>
        // POST api/<UsersController>
        [HttpPost]
        public string Post([FromBody]Users item)
        {
            var user = new Users
            {
                Username = item.Username,
                Avatar = item.Avatar,
                Remarks = item.Remarks
            };


            _usersRespository.Add(user);

            var res = new
            {
                Code = 1000,
                Data = GetDynamic(user),
                Msg = "添加用户成功"
            };

            return JsonHelper.SerializeObject(res);
        }

        // PUT api/<UsersController>/5
        [HttpPut("{id}")]
        public string Put(int id, [FromBody] Users value)
        {
            var user = _usersRespository.GetById(id);
            dynamic res;

            if (user != null)
            {
                user.Username = value.Username;
                user.Remarks = value.Remarks;
                user.Avatar = value.Avatar;
                _usersRespository.Update(user);
                res = new
                {
                    Code = 1000,
                    Data =GetDynamic(user) ,
                    Msg = "修改用户成功"
                };
            }
            else
            {
                res = new
                {
                    Code = 1002,
                    Data = "",
                    Msg = "指定用户不存在"
                };
            }


            return JsonHelper.SerializeObject(res);
        }

        // DELETE api/<UsersController>/5
        [HttpDelete("{id}")]
        public string Delete(int id)
        {
            var user = _usersRespository.GetById(id);
            dynamic res;

            if (user != null)
            {
                user.IsDeleted = true;
                _usersRespository.Update(user);
                res = new
                {
                    Code = 1000,
                    Data = "",
                    Msg = "删除指定用户成功"
                };
            }
            else
            {
                res = new
                {
                    Code = 1005,
                    Data = "",
                    Msg = "指定用户不存在"
                };
            }

            return JsonHelper.SerializeObject(res);
        }



        /// <summary>
        /// 登录，以获取AccessToken
        /// </summary>
        /// <param name="loginInfo">登录信息，包括用户名和密码</param>
        /// <returns></returns>
        [HttpPost, Route("login")]
        [AllowAnonymous]
        public ActionResult Login([FromBody] LoginDTO loginInfo)
        {
            if (loginInfo.Username == null || loginInfo.Password == null)
            {
                return BadRequest("错误的请求");
            }

            var user = _usersRespository.Table.Where(x => x.Username == loginInfo.Username).FirstOrDefault();

            if (user != null)
            {
                if (user.IsDeleted)
                {
                    return Ok(new { code = 1001, data = "", msg = "当前用户己删除" });
                }
                else
                {
                    if (user.IsActived)
                    {
                        if (user.Password == loginInfo.Password)
                        {
                            var token = TokenHelper.GenerateToken(user, "Admin", _tokenParameter);
                            var refreshToken = "112358";
                            return Ok(new { code = 1000, data = new { token }, refreshToken, msg = "登录成功" });
                        }
                        else
                        {
                            return Ok(new { code = 1002, data ="",msg = "用户名或密码错误" });
                        }
                    }
                    else
                    {
                        return Ok(new { code = 1003, data = "", msg = "当前用户己禁用" });
                    }
                }
            }
            else
            {
                return Ok(new {code=1004,data="" ,msg="当前用户未注册"});
            }

            //var token =TokenHelper.GenerateToken(loginInfo.Username, "Admin",_tokenParameter);
            //var refreshToken = "112358";
            //return Ok(new {code=1000,data=new { token }, refreshToken,msg="登录成功" });
            //return Ok(new { accessToken = token, refreshToken });
        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpGet,Route("getUserInfo")]
        public ActionResult GetUserInfo(string token)
        {
            //var token = HttpContext.Request.Headers["authorization"].ToString();
            var jwtInfo = new JwtSecurityToken(token);
            var userIdString = jwtInfo.Claims.FirstOrDefault(x => x.Type == "userId").Value;
            var userId = int.Parse(userIdString);
            var accessList = new List<string>
            {
                "dashboard",
                "users",
                "roles",
                "setting",
                "articles"
            };
            dynamic info;
            var user = _usersRespository.GetById(userId);

            if (user != null)
            {
                info = new
                {
                    name = "admin",
                    roles = "roles",
                    avatar = string.IsNullOrEmpty(user.Avatar)?"https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif": user.Avatar,
                    access = accessList
                };
            }
            else
            {
                info = new
                {

                };
            }

            
            return Ok(new { code = 1000, data = info,  msg = "获取用户信息成功" });
            //return Ok(new { accessToken = token, refreshToken });
        }

        /// <summary>
        /// 登出
        /// </summary>
        /// <param name="loginInfo"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost,Route("logout")]
        public ActionResult Logout()
        {
            //if (loginInfo.Username == null || loginInfo.Password == null)
            //{
            //    return BadRequest("错误的请求");
            //}

            //var token = TokenHelper.GenerateToken(loginInfo.Username, "Admin", _tokenParameter);
            //var refreshToken = "112358";
            return Ok(new { code = 1000, data="", msg = "登出成功" });
            //return Ok(new { accessToken = token, refreshToken });
        }

        /// <summary>
        /// 使用RefreshToken，刷新AccessToken，避免重新登录获取AccessToken（有点Low不是吗）
        /// </summary>
        /// <param name="request">请求信息，包括AccessToken和RefreshToken</param>
        /// <returns></returns>
        [HttpPost, Route("refreshAccessToken")]
        [AllowAnonymous]
        public ActionResult RefreshAccessToken([FromBody] RefreshTokenDTO request)
        {
            if (request.AccessToken == null && request.RefreshToken == null)
            {
                return BadRequest("Invalid Request");
            }

            //这儿是验证Token的代码
            var handler = new JwtSecurityTokenHandler();
            try
            {
                ClaimsPrincipal claim = handler.ValidateToken(request.AccessToken, new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenParameter.Secret)),
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    ValidateLifetime = false,
                }, out SecurityToken securityToken);
                var username = claim.Identity.Name;
                var user=_usersRespository.Table.Where(x => x.Username == username).FirstOrDefault();
                //这儿是生成Token的代码
                var token =TokenHelper.GenerateToken(user, "Admin",_tokenParameter);
                //此处的RefreshToken是直接指定和字符串，在正式项目中，应该是一个可验证的加密串，如md5、hash等
                var refreshToken = "654321";
                return Ok(new { accessToken = token, refreshToken });
            }
            catch (Exception)
            {
                return BadRequest("Invalid Request");
            }
        }

        [HttpPost,Route("{id}/updateUserRole")]
        public string UpdateUserRole(int id, [FromBody] int[] value)
        {
            var user = _usersRespository.GetById(id);
            dynamic res;

            if (user != null)
            {
                var userRole = _userRoleRespository.Table.Where(x => x.UsersId == id).ToList();
                _userRoleRespository.Delete(userRole);

                var list = new List<UserRole>();
                foreach(var item in value)
                {
                    list.Add(new UserRole
                    {
                        UsersId = id,
                        RolesId = item
                    });
                }

                _userRoleRespository.Add(list);
                
                res = new
                {
                    Code = 1000,
                    Data = GetDynamic(user),
                    Msg = "修改用户角色成功"
                };
            }
            else
            {
                res = new
                {
                    Code = 1002,
                    Data = "",
                    Msg = "指定用户不存在"
                };
            }


            return JsonHelper.SerializeObject(res);
        }

        [HttpPost,Route("upload")]
        public string UploadFiles(IFormCollection request)
        {
            string path = _configuration.GetSection("UploadPath").Value;
            var files = request.Files;

            var filePathList = new List<string>();

            foreach(var file in files)
            {
                var fileName = file.FileName;
                var extName = fileName.Substring(fileName.LastIndexOf("."));//extName包含了“.”
                string randName = Guid.NewGuid().ToString("N");// 654sdfasdfkejr

                var tempPath = string.Format("{0}{1}",randName,extName);

                var prePath = Path.Combine(_env.ContentRootPath,"wwwroot",path);

                var fullPath = Path.Combine(prePath, tempPath);

                if (!Directory.Exists(prePath))
                {
                    Directory.CreateDirectory(prePath);
                }

                using (var stream = new FileStream(fullPath, FileMode.Create))
                {

                    //再把文件保存的文件夹中
                    file.CopyTo(stream);

                }

                var realtivePath = string.Format("{0}/{1}{2}",path,randName,extName);

                filePathList.Add(realtivePath);
            }



            var res = new
            {
                Code = 1000,
                Data = filePathList,
                Msg = "图片上传成功"
            };
            return JsonHelper.SerializeObject(res);
        }

        [HttpPost, Route("{id}/status")]
        public string UpdateUserStatus(int id)
        {
            var user = _usersRespository.GetById(id);
            dynamic res;

            if (user != null)
            {
                user.IsActived = !user.IsActived;
                _usersRespository.Update(user);

                res = new
                {
                    Code = 1000,
                    Data = GetDynamic(user),
                    Msg = "修改用户状态成功"
                };
            }
            else
            {
                res = new
                {
                    Code = 1002,
                    Data = "",
                    Msg = "指定用户不存在"
                };
            }


            return JsonHelper.SerializeObject(res);
        }

        private dynamic GetDynamic(Users user)
        {
            var rolesId = _userRoleRespository.Table.Where(x => x.UsersId == user.Id).Select(x => x.RolesId).ToList();
            return new
            {
                user.Id,
                user.Username,
                user.Remarks,
                user.Avatar,
                IsActived =user.IsActived?1:0,
                Roles = rolesId
            };
        }

        private dynamic GetDynamic(Pagination<Users> pagination)
        {
            var users = pagination.List;
            var userRole = _userRoleRespository.Table
                .Where(x => users.Select(t => t.Id).Contains(x.UsersId))
                .Select(x => new { x.Id, x.UsersId, x.RolesId })
                .ToList();

            var list = new List<dynamic>();

            foreach(var user in users)
            {
                list.Add(new
                {
                    user.Id,
                    user.Username,
                    user.Remarks,
                    user.Avatar,
                    IsActived = user.IsActived ? 1 : 0,
                    Roles = userRole.Where(x => x.UsersId == user.Id).Select(x => x.RolesId).ToList()
                });
            }

            var data = new
            {
                pagination.PageIndex,
                pagination.PageSize,
                pagination.TotalItem,
                pagination.TotalPage,
                List = list
            };
            return data;
        }
    }
}
